import java.io.File;
import java.io.IOException;
import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;

/**
 * Class gathering every parameters of the simulation from the file param.ini
 * Desing Pattern: Singleton
 * @author Luc Peres
 * @version 2.0
 */
public class Param {

	private Ini params;
	
	/**
	 * Check if the param.ini file already exists, if not it creates it
	 */
	private Param(){
		File file = new File("param.ini");
		if (file.exists()) {
			try {
				params = new Ini(file);
			} catch (InvalidFileFormatException e) {
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else
		{
			try {
				this.createFile(file);
				System.out.println("Parameter file created. (" + file.getCanonicalPath() + ")");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * creates the Cell initialization part of the new param.ini file
	 */
	private void cellInitialization() {
		Ini.Section sec;
		params.add("Cell/initialization");
		sec = params.get("Cell/initialization");
		sec.put("GSH", "0.0");
		sec.put("GSSG", "0.0");
		sec.put("Gor", "0.0");
		sec.put("ArcB", "0.0");
		sec.put("ArcA-P", "0.0");
		sec.put("Cbl", "0.0");
		sec.put("gshA", "0.0");
		sec.put("gshB", "0.0");
		sec.put("put", "0.0");
		sec.put("fimB", "0.0");
		sec.put("FimB", "0.0");
		sec.put("fimS", "0.0");
	}
	
	/**
	 * creates the Periplasm initialization part of the new param.ini file
	 */
	private void periplasmInitialization() {
		Ini.Section sec;
		params.add("Periplasm/initialization");
		sec = params.get("Periplasm/initialization");
		sec.put("GSH", "0.0");
		sec.put("GSSG", "0.0");
		sec.put("O2", "0.0");
	}
	
	/**
	 * creates the Cell ratios part of the new param.ini file
	 */
	private void cellRatio() {
		Ini.Section sec;
		params.add("Cell/ratio");
		sec = params.get("Cell/ratio");
		sec.put("GSSG --> GSH", "0.0");
		sec.put("Gor --<> GSH", "0.0");
		sec.put("gshA --> GSH", "0.0");
		sec.put("gshB --> GSH", "0.0");
		sec.put("Cbl --<> gshA", "0.0");
		sec.put("Cbl --<> gshB", "0.0");
		sec.put("GSH --> GSSG", "0.0");
		sec.put("GSSG --<> fimS", "0.0");
		sec.put("ArcB --> ArcA-P", "0.0");
		sec.put("ArcA-P --<> fimS", "0.0");
		sec.put("put --<> fimB", "0.0");
		sec.put("fimB --> FimB", "0.0");
		sec.put("FimB --> fimS", "0.0");
	}
	
	/**
	 * creates the Periplasm ratios part of the new param.ini file
	 */
	private void periplasmRatio() {
		Ini.Section sec;
		params.add("Periplasm/ratio");
		sec = params.get("Periplasm/ratio");
		sec.put("GSH --> GSSG", "0.0");
		sec.put("O2 --> GSSG", "0.0");
	}
	
	/**
	 * creates the Cell/Periplasm ratios part of the new param.ini file
	 */
	private void cellPeriplasmRatio() {
		Ini.Section sec;
		params.add("CellPeriplasm/ratio");
		sec = params.get("CellPeriplasm/ratio");
		sec.put("O2(Periplasm) --<> ArcB(Cell)", "0.0");
		sec.put("GSH(Cell) --> GSH(Periplasm)", "0.0");
		sec.put("GSH(Periplasm) --<> put(Cell)", "0.0");
	}
	
	/**
	 * Creates the new param.ini file
	 * @param file: param.ini
	 * @throws IOException
	 */
	private void createFile(File file) throws IOException{
		file.createNewFile();
		params = new Ini(file);
		
		Ini.Section sec;
		params.add("Simulation");
		sec = params.get("Simulation");
		sec.put("Cycle Number", "0");
		
		cellInitialization();
		periplasmInitialization();
		
		cellRatio();
		periplasmRatio();
		cellPeriplasmRatio();
		
		params.store();
	}
	
	/**
	 * get the parameters list
	 * @return: Ini instance
	 */
	public Ini getParams() {
		return this.params;
	}
	
	/**
	 * Creates the unique instance of Param class if not already created (Singleton design pattern)
	 * @return
	 */
	public static Param getParam() {
		if (param == null){
			param = new Param();
		}
		return param;
	}
	
	/**
	 * Unique instance of Param (Singleton design pattern)
	 */
	private static Param param;
}
